#include <cppunit/config/SourcePrefix.h>
#include "TestDesignExtractor.h"
#include <algorithm>
using namespace std;

void TestDesignExtractor::setUp() {
	n[0] = new Node(new Program());
	n[1] = new Node(new Procedure(0));
	n[2] = new Node(new StmtList());
	n[3] = new Node(new Assign(),1);
	n[4] = new Node(new Variable(0),1);
	n[5] = new Node(new Plus(),1);
	n[6] = new Node(new Plus(),1);
	n[7] = new Node(new Variable(1),1);
	n[8] = new Node(new Constant(3),1);
	n[9] = new Node(new Variable(2),1);
	n[10] = new Node(new While(),2);
	n[11] = new Node(new Variable(3),2);
	n[12] = new Node(new StmtList());
	n[13] = new Node(new Assign(),3);
	n[14] = new Node(new Variable(0),3);
	n[15] = new Node(new Variable(2),3);
	n[16] = new Node(new Assign(),4);
	n[17] = new Node(new Variable(2),4);
	n[18] = new Node(new Plus(),4);
	n[19] = new Node(new Variable(1),4);
	n[20] = new Node(new Constant(3),4);

	programAST.setRoot(n[0]);
	n[0]->addChildNode(n[1]);
	n[1]->addChildNode(n[2]);
	n[2]->addChildNode(n[3]);
	n[2]->addChildNode(n[10]);
	n[3]->addChildNode(n[4]);
	n[3]->addChildNode(n[5]);
	n[5]->addChildNode(n[6]);
	n[5]->addChildNode(n[9]);
	n[6]->addChildNode(n[7]);
	n[6]->addChildNode(n[8]);
	n[10]->addChildNode(n[11]);
	n[10]->addChildNode(n[12]);
	n[12]->addChildNode(n[13]);
	n[12]->addChildNode(n[16]);
	n[13]->addChildNode(n[14]);
	n[13]->addChildNode(n[15]);
	n[16]->addChildNode(n[17]);
	n[16]->addChildNode(n[18]);
	n[18]->addChildNode(n[19]);
	n[18]->addChildNode(n[20]);
}

void TestDesignExtractor::tearDown() {
	for(int i=0;i<NNODES;i++){
		delete n[i]->getDesignEntity();
		delete n[i];
	}
}

CPPUNIT_TEST_SUITE_REGISTRATION( TestDesignExtractor );

void TestDesignExtractor::testCreateModifiesTable(){		
	Modifies modTable;
	DesignExtractor DEx(programAST);

	DEx.createModifiesTable(modTable);
	vector<pair<int,int> > v = modTable.getModifiesStatement(ANYVALUE,ANYVALUE);
	CPPUNIT_ASSERT_MESSAGE("Variable 'x'(0) is modified at stmt number 1",
							find(v.begin(), v.end(), pair<int,int>(1,0)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'x'(0) is modified at stmt number 2",
							find(v.begin(), v.end(), pair<int,int>(2,0)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'z'(2) is modified at stmt number 2",
							find(v.begin(), v.end(), pair<int,int>(2,2)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'x'(0) is modified at stmt number 3",
							find(v.begin(), v.end(), pair<int,int>(3,0)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'z'(2) is modified at stmt number 4",
							find(v.begin(), v.end(), pair<int,int>(4,2)) != v.end());
	CPPUNIT_ASSERT_EQUAL_MESSAGE("There are 5 modifies relationship", 5, (int) v.size());
}

void TestDesignExtractor::testCreateUsesTable(){
	Uses usesTable;
	DesignExtractor DEx(programAST);

	DEx.createUsesTable(usesTable);
	vector<pair<int,int> > v = usesTable.getUsesStatement(ANYVALUE,ANYVALUE);

	CPPUNIT_ASSERT_MESSAGE("Variable 'y'(1) is used at stmt number 1",
							find(v.begin(), v.end(), pair<int,int>(1,1)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'z'(2) is used at stmt number 1",
							find(v.begin(), v.end(), pair<int,int>(1,2)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'i'(3) is used at stmt number 2",
							find(v.begin(), v.end(), pair<int,int>(2,3)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'y'(1) is used at stmt number 2",
							find(v.begin(), v.end(), pair<int,int>(2,1)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'z'(2) is used at stmt number 2",
							find(v.begin(), v.end(), pair<int,int>(2,2)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'z'(2) is used at stmt number 3",
							find(v.begin(), v.end(), pair<int,int>(3,2)) != v.end());
	CPPUNIT_ASSERT_MESSAGE("Variable 'y'(1) is used at stmt number 4",
							find(v.begin(), v.end(), pair<int,int>(4,1)) != v.end());
	CPPUNIT_ASSERT_EQUAL_MESSAGE("There are 7 uses relationship", 7, (int) v.size());
}